package uk.ac.cam.cl.oscar;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.*;
import java.util.Stack;
import java.util.Vector;
import javax.swing.JApplet;
import javax.swing.*;
import uk.ac.cam.cl.oscar.MMS_server.MainServer;
import uk.ac.cam.cl.oscar.Oscar_Mobile_Server.Main;
import uk.ac.cam.cl.oscar.sift.Keypoint;

/**
 *
 * @author voydmayne
 */

class DisplayImage{
    BufferedImage img;
}

public class Demonstration extends JFrame implements KeyListener{
    
    public static Demonstration DemoAppInst;
    private static DisplayImage[] stkImages = new DisplayImage[6];
    private static int pointer=0;
    
    private static String currentID = "";
    private static Runnable currentThread;
    
    private static BufferedImage imgInit;
    private static BufferedImage imgEdgy;
    private static BufferedImage imgFramed;
    private static BufferedImage imgCropped;
    private static BufferedImage imgKP;
    private static BufferedImage imgMatch;
    private final int IMGWIDTH = 500;
    private final int IMGHEIGHT = 375;
    
    private int origWidth, origHeight;
    private int croppedWidth, croppedHeight;
    
    public static void main(String[] args){
        
        //disable native accelerator
        System.setProperty("com.sun.media.jai.disableMediaLib", "true");
        Demonstration demo = new Demonstration();
        
        DemoAppInst = demo;
        demo.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {System.exit(0);}
        });
        demo.setVisible(true);
        
        demo.setPreferredSize(new Dimension(1600,900));
        demo.pack();
        demo.addKeyListener(demo);
        
        //MainServer MainServerInst = new MainServer();
        //(new Thread(MainServerInst)).start();
        
        Main MainInst = new Main();
        (new Thread(MainInst)).start();
        
        
        DemoTester dt1 = new DemoTester("c://academia/oscar/source/tests/2low3.jpg");
      //  dt1.runTest();
        
                
    }
    
    
    public void processNewRequest(Runnable request){
        System.out.println("Demo: New Request");
        
        pointer = 0;
        
        //TODO: make sure only one request is being displayed
        //currentID = threadID;
        if (currentThread != null){
            //currentThread.setPriority(Thread.MIN_PRIORITY); 
            
        }
        currentThread = request;
        
        imgInit = makeDefaultImage(IMGWIDTH, IMGHEIGHT);
        imgEdgy = makeDefaultImage(IMGWIDTH, IMGHEIGHT);
        imgFramed = makeDefaultImage(IMGWIDTH, IMGHEIGHT);
        imgCropped = makeDefaultImage(IMGWIDTH, IMGHEIGHT);
        imgKP = makeDefaultImage(IMGWIDTH, IMGHEIGHT);
        imgMatch = makeDefaultImage(IMGWIDTH, IMGHEIGHT);
        
        this.repaint();
        
    }
    
    public void displayNewInitImage(String threadID, BufferedImage img){        
        
        System.out.println("Demo: New Initial Image");        
        imgInit = new BufferedImage(IMGWIDTH, IMGHEIGHT, BufferedImage.TYPE_INT_RGB);
        imgInit.getGraphics().drawImage(img, 0, 0, IMGWIDTH, IMGHEIGHT, new Color(0,0,0), null);  
        
        origWidth = img.getWidth();
        origHeight = img.getHeight();
       // System.out.println(origWidth);
        DisplayImage di = new DisplayImage();
        di.img = imgInit;        
        Push(di);
        
        repaint();
    }
    
    
    
    public void displayNewEdgyImage(String threadID, BufferedImage img){        
        if (threadID.compareTo(currentID) != 0){
      //      return;
        }
        System.out.println("Demo: New Edgy Image");        
        imgEdgy = new BufferedImage(IMGWIDTH, IMGHEIGHT, BufferedImage.TYPE_INT_RGB);
        imgEdgy.getGraphics().drawImage(img, 0, 0, IMGWIDTH, IMGHEIGHT, new Color(0,0,0), null);      
        
        DisplayImage di = new DisplayImage();
        di.img = imgEdgy;        
        Push(di);
        
        repaint();
    }
    
    
    
    public void displayNewFramedImage(double xtl, double ytl, double xtr, double ytr, double xbl, double ybl, double xbr, double ybr){
        System.out.println("Demo: New Framed Image");        
        imgFramed = new BufferedImage(IMGWIDTH, IMGHEIGHT, BufferedImage.TYPE_INT_RGB);
        Graphics g = imgFramed.getGraphics();
        g.drawImage(imgEdgy, 0, 0, IMGWIDTH, IMGHEIGHT, new Color(0,0,0), null);   
        g.setColor(new Color(255,255,255));
        //System.out.println(xtl);
        xtl *= (double)IMGWIDTH / (double)origWidth;
        ytl *= (double)IMGHEIGHT / (double)origHeight;
        xtr *= (double)IMGWIDTH / (double)origWidth;
        ytr *= (double)IMGHEIGHT / (double)origHeight;
        xbl *= (double)IMGWIDTH / (double)origWidth;
        ybl *= (double)IMGHEIGHT / (double)origHeight;
        xbr *= (double)IMGWIDTH / (double)origWidth;
        ybr *= (double)IMGHEIGHT / (double)origHeight;
        //System.out.println(xtl);
        g.drawLine((int)xtl, (int)ytl, (int)xtr, (int)(ytr));
        g.drawLine((int)xtr, (int)ytr, (int)xbr, (int)(ybr));
        g.drawLine((int)xbr, (int)ybr, (int)xbl, (int)(ybl));
        g.drawLine((int)xbl, (int)ybl, (int)xtl, (int)(ytl));   
        
        DisplayImage di = new DisplayImage();
        di.img = imgFramed;        
        Push(di);
        
        repaint();
        
    }
    
    public void displayNewCroppedImage(String threadID, BufferedImage img){        
        if (threadID.compareTo(currentID) != 0){
      //      return;
        }
        System.out.println("Demo: New Cropped Image");        
        imgCropped = new BufferedImage(IMGWIDTH, IMGHEIGHT, BufferedImage.TYPE_INT_RGB);
        imgCropped.getGraphics().drawImage(img, 0, 0, IMGWIDTH, IMGHEIGHT, new Color(0,0,0), null);    
        
        DisplayImage di = new DisplayImage();
        di.img = imgCropped;        
        Push(di);
        
        repaint();
    }
    
    public void displayNewKPImage(BufferedImage img, Vector<Keypoint> kps){
        
        System.out.println("Demo: New Keypoint Image");        
        imgKP = new BufferedImage(IMGWIDTH, IMGHEIGHT, BufferedImage.TYPE_INT_RGB);
        Graphics g = imgKP.getGraphics();
        g.drawImage(imgCropped, 0, 0, IMGWIDTH, IMGHEIGHT, new Color(0,0,0), null);   
        g.setColor(new Color(255,255,0));
        //g.setXORMode(new Color(255,0,0));
        int w = img.getWidth();
        int h = img.getHeight();
        
        
        for (int i=0; i<kps.size(); i++) {
           Keypoint kp = kps.elementAt(i);
           int x = (int)Math.round(kp.getX() * (double)IMGWIDTH/(double)w);
           int y = (int)Math.round(kp.getY() * (double) IMGHEIGHT/(double)h);

           g.drawLine(x-2, y, x+2, y);
           g.drawLine(x, y-2, x, y+2);
        }
        
        DisplayImage di = new DisplayImage();
        di.img = imgKP;        
        Push(di);
        
        repaint();
    }
    
    public void displayNewMatch(BufferedImage img){
        System.out.println("Demo: New Matching Image");        
        imgMatch = new BufferedImage(IMGWIDTH, IMGHEIGHT, BufferedImage.TYPE_INT_RGB);
        imgMatch.getGraphics().drawImage(img, 0, 0, IMGWIDTH, IMGHEIGHT, new Color(0,0,0), null);  
        
       // origWidth = img.getWidth();
        //origHeight = img.getHeight();
       // System.out.println(origWidth);
        DisplayImage di = new DisplayImage();
        di.img = imgMatch;        
        Push(di);
        
        repaint();
    }
    
    public void skipFramedImage(){
        System.out.println("Demo: Skipped Framed Image");        
        imgFramed = new BufferedImage(IMGWIDTH, IMGHEIGHT, BufferedImage.TYPE_INT_RGB);
        Graphics g = imgFramed.getGraphics();
        g.drawImage(imgEdgy, 0, 0, IMGWIDTH, IMGHEIGHT, new Color(0,0,0), null); 
    }
    
    private static BufferedImage makeDefaultImage(int width, int height){
        BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        img.getGraphics().setColor(new Color(0,0,0));      
        
        img.getGraphics().clearRect(0, 0, width, height);
        img.getGraphics().drawString("processing...", 200, 180);
        
        return img;
    }
    
    private void Push(DisplayImage di){
        stkImages[pointer] = di;
        pointer++;
    }
    
    private DisplayImage Pop(){
        pointer--;
        return stkImages[pointer];
        
    }
    
    
    public void paint(Graphics g){ 
        int[] xCoords = {20, 550, 1080, 20, 550, 1080};
        int[] yCoords = {30, 30, 30, 435, 435, 435};
        
        g.setColor(new Color(100,100,100));
        g.fillRect(0,0, this.getWidth(), this.getHeight());
        
        for(int i=0; i<pointer; i++){
            g.drawImage(stkImages[i].img, xCoords[i], yCoords[i], null);            
        }
        
       /* g.drawImage(imgInit, 20, 30, null);
        g.drawImage(imgEdgy, 550, 30, null);
        g.drawImage(imgFramed, 1080, 30, null);
        g.drawImage(imgCropped, 20, 435, null);
        g.drawImage(imgKP, 550, 435, null);*/
        
        
        
        
        
    }
    
    public void update(){
        repaint();
    }

    public void keyTyped(KeyEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
        
    }

    public void keyPressed(KeyEvent e) {
        //System.out.println("Key pressed");
        //DemoTester dt1 = new DemoTester("c://academia/oscar/source/tests/2low1.jpg");
        ///dt1.runTest();
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    public void keyReleased(KeyEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    public void mouseClicked(MouseEvent e) {
        
    }

    public void mousePressed(MouseEvent e) {
        
    }

    public void mouseReleased(MouseEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void mouseEntered(MouseEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void mouseExited(MouseEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
    
}
